package ffte.property

import spinal.core._
import ffte.default.config

/**
 * FFT RTL generation configuration case class
 *
 * This class defines the RTL (Register Transfer Level) generation configuration
 * parameters that control hardware implementation details and optimization
 * strategies for FFT components.
 *
 * Configuration Parameters:
 * - complexMulFast: Complex multiplication method selection (true=4-mul fast, false=3-mul optimized)
 * - symmetric: Fixed-point symmetry mode for signed number handling
 * - resolution: Default fractional bit resolution for fixed-point numbers
 * - twiddleResolution: Fractional bits for twiddle factor storage
 * - shiftMethod: Function determining scaling shift values for different FFT stages
 *
 * Hardware Optimization Impact:
 * - Area vs. performance trade-offs in complex multiplication
 * - Precision management in fixed-point arithmetic
 * - Twiddle factor storage optimization
 * - Dynamic scaling strategies for overflow prevention
 *
 * @param complexMulFast Complex multiplication algorithm selection
 * @param symmetric Fixed-point signed number symmetry mode
 * @param resolution Default fractional bit resolution
 * @param twiddleResolution Twiddle factor fractional bit resolution
 * @param shiftMethod Dynamic scaling function for FFT stages
 */
case class FFTRTLConfig(
      complexMulFast    : Boolean
    , symmetric         : Boolean
    , resolution        : Int
    , twiddleResolution : Int
    , shiftMethod       : (Int) => Int
){

    /**
     * Apply RTL configuration to a code block
     *
     * Sets this RTL configuration as active within the specified code block
     * and restores the previous configuration afterward.
     *
     * @param body Code block to execute with this RTL configuration
     * @tparam B Return type of the code block
     * @return Result of executing the code block with this RTL configuration
     */
    def on[B](body : => B) = {
        FFTGenRTLProperty(this) on {
            body
        }
    }

    /**
     * Alternative syntax for RTL configuration application
     *
     * Provides a more natural function-call syntax for applying
     * RTL configuration to a code block.
     *
     * @param body Code block to execute with this RTL configuration
     * @tparam B Return type of the code block
     * @return Result of executing the code block with this RTL configuration
     */
    def apply[B](body : => B): B = on(body)
}

/**
 * FFT RTL configuration property manager
 *
 * This object extends SpinalHDL's ScopeProperty to provide hierarchical
 * configuration management for RTL generation parameters. It allows RTL
 * configurations to be applied to specific scopes and automatically
 * restored when exiting those scopes.
 *
 * Features:
 * - Hierarchical RTL configuration with automatic restoration
 * - Default RTL configuration fallback
 * - Thread-safe configuration management
 * - Integration with SpinalHDL's configuration system
 *
 * Applications:
 * - Component-level hardware optimization
 * - Algorithm selection for complex arithmetic
 * - Precision management across FFT implementations
 * - Dynamic scaling strategy configuration
 */
object FFTGenRTLProperty extends ScopeProperty[FFTRTLConfig] {

    /**
     * Default RTL configuration fallback
     *
     * Provides the default RTL configuration values when no specific
     * configuration is active in the current scope.
     */
    override def default: FFTRTLConfig = config.DefaultFFTGenRTLConfig
}

/**
 * Complex multiplication method accessor
 *
 * This object provides access to the current complex multiplication algorithm
 * selection from the active RTL configuration.
 *
 * Algorithm Options:
 * - true: Fast 4-multiplication method (direct implementation)
 * - false: Optimized 3-multiplication method (reduced resource usage)
 *
 * Usage:
 * ```scala
 * val useFastMethod = getComplexMulMethod()
 * ```
 */
object getComplexMulMethod {

    /**
     * Get the current complex multiplication method
     *
     * Retrieves the complex multiplication algorithm selection from the
     * active RTL configuration. If no specific configuration is active,
     * returns the default value.
     *
     * @return true for fast 4-mul method, false for optimized 3-mul method
     */
    def apply(): Boolean = FFTGenRTLProperty.get.complexMulFast
}

/**
 * Fixed-point symmetry mode accessor
 *
 * This object provides access to the current fixed-point symmetry mode
 * from the active RTL configuration.
 *
 * Usage:
 * ```scala
 * val useSymmetry = getFixSym()
 * ```
 */
object getFixSym{

    /**
     * Get the current fixed-point symmetry mode
     *
     * Retrieves the symmetry mode selection from the active RTL configuration.
     * If no specific configuration is active, returns the default value.
     *
     * @return true if symmetry mode is enabled
     */
    def apply(): Boolean = FFTGenRTLProperty.get.symmetric
}

/**
 * Default resolution accessor
 *
 * This object provides access to the current default fractional bit
 * resolution from the active RTL configuration.
 *
 * Usage:
 * ```scala
 * val resolution = getResolution()
 * ```
 */
object getResolution {

    /**
     * Get the current default resolution
     *
     * Retrieves the default fractional bit resolution from the active
     * RTL configuration. If no specific configuration is active,
     * returns the default value.
     *
     * @return Current default fractional bit resolution
     */
    def apply(): Int = FFTGenRTLProperty.get.resolution
}

/**
 * Twiddle resolution accessor
 *
 * This object provides access to the current twiddle factor fractional
 * bit resolution from the active RTL configuration.
 *
 * Usage:
 * ```scala
 * val twiddleRes = getTwiddleResolution()
 * ```
 */
object getTwiddleResolution {

    /**
     * Get the current twiddle resolution
     *
     * Retrieves the twiddle factor fractional bit resolution from the
     * active RTL configuration. If no specific configuration is active,
     * returns the default value.
     *
     * @return Current twiddle factor fractional bit resolution
     */
    def apply(): Int = FFTGenRTLProperty.get.twiddleResolution
}

/**
 * Shift method accessor
 *
 * This object provides access to the current dynamic scaling function
 * from the active RTL configuration.
 *
 * Usage:
 * ```scala
 * val shiftValue = getShiftMethod(stageIndex)
 * ```
 */
object getShiftMethod {

    /**
     * Get the current shift method for a given stage
     *
     * Retrieves the dynamic scaling value for the specified FFT stage
     * from the active RTL configuration. If no specific configuration
     * is active, returns the default value.
     *
     * @param n FFT stage index or parameter
     * @return Shift amount for the specified stage
     */
    def apply(n:Int):Int = FFTGenRTLProperty.get.shiftMethod(n)
}
